package com.ruoyi.common.core.domain;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.*;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.utils.CollectionUtils;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
import org.springframework.util.NumberUtils;

/**
 * 响应信息主体
 *
 * @author ruoyi
 */
@Getter
public class R<T> implements Serializable
{
    private static final long serialVersionUID = 1L;

    /** 成功 */
    public static final int SUCCESS = HttpStatus.SUCCESS;

    /** 失败 */
    public static final int FAIL = HttpStatus.ERROR;

    @Schema(description = "响应编码，成功为 200", example = "200")
    private int code;

    @Schema(description = "响应消息", example = "执行成功")
    private String msg;

    @Schema(description = "响应数据")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private T data;

    @Schema(description = "响应时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    private LocalDateTime time;

    public static <T> R<T> ok()
    {
        return of(SUCCESS, "操作成功", null);
    }

    public static <T> R<T> ok(T data)
    {
        return of(SUCCESS, "操作成功", data);
    }

    public static <T> R<T> ok(String msg, T data)
    {
        return of(SUCCESS, msg, data);
    }

    public static <T> R<T> ok(String msg)
    {
        return of(SUCCESS, msg, null);
    }

    public static <T> R<T> fail()
    {
        return of(FAIL, "操作失败", null);
    }

    public static <T> R<T> fail(String msg)
    {
        return of(FAIL, msg, null);
    }

    public static <T> R<T> fail(T data)
    {
        return of(FAIL, "操作失败", data);
    }

    public static <T> R<T> fail(String msg, T data)
    {
        return of(FAIL, msg, data);
    }

    public static <T> R<T> fail(int code)
    {
        return of(code, "操作失败", null);
    }

    public static <T> R<T> fail(int code, String msg)
    {
        return of(code, msg, null);
    }

    public static <T> R<T> fail(int code, T data)
    {
        return of(code, "操作失败", data);
    }


//    public static R<RowsResult> rows(Integer rows)
//    {
//        Aff result = new RowsResult(rows);
//        return rows > 0 ? R.ok() : R.fail();
//    }

    public static R<AffectedRows> rows(Integer rows)
    {
        AffectedRows result = new AffectedRows(rows);
        return rows > 0 ? R.ok(result) : R.fail(result);
    }

    public static <T> R<T> result(Integer rows)
    {
        return rows > 0 ? R.ok() : R.fail();
    }

    public static <T> R<T> result(boolean result)
    {
        return result ? R.ok() : R.fail();
    }

    public static <T> R<T> of(int code, String msg)
    {
        return of(code, msg, null);
    }

    public static <T> R<T> of(int code, String msg, T data)
    {
        R<T> result = new R<>();
        result.code = code;
        result.data = data;
        result.msg = msg;
        result.time = LocalDateTime.now();
        return result;
    }

//    public int getCode()
//    {
//        return code;
//    }
//
//    public void setCode(int code)
//    {
//        this.code = code;
//    }
//
//    public String getMsg()
//    {
//        return msg;
//    }
//
//    public void setMsg(String msg)
//    {
//        this.msg = msg;
//    }
//
//    public T getData()
//    {
//        return data;
//    }
//
//    public void setData(T data)
//    {
//        this.data = data;
//    }
//
//    public static <T> Boolean isError(R<T> ret)
//    {
//        return !isSuccess(ret);
//    }
//
//    public static <T> Boolean isSuccess(R<T> ret)
//    {
//        return R.SUCCESS == ret.getCode();
//    }

    public static RMapBuilder put(String key, Object value)
    {
        return new RMapBuilder().put(key, value);
    }

    public static class RMapBuilder
    {
        private int code = SUCCESS;
        private String msg = "执行成功";
        private Map<String, Object> data = new HashMap<>();

        public RMapBuilder code(int code)
        {
            this.code = code;
            return this;
        }

        public RMapBuilder msg(String msg)
        {
            this.msg = msg;
            return this;
        }

        public RMapBuilder data(Map<String, Object> data)
        {
            this.data.putAll(data);
            return this;
        }

        public RMapBuilder put(String key, Object value)
        {
            this.data.put(key, value);
            return this;
        }

        public R build()
        {
            return R.of(code, msg, CollectionUtils.isNotEmpty(data) ? data : null);
        }
    }
}
